# @Time : 2024-11-02 14:28
# @Author : Fioman 
# @Phone : 13149920693
"""
线程池: 管理和复用一组线程,而不是为每一个任务都创建和销毁一个线程.
主要目的是提供程序的性能和资源利用率,减少线程创建和销毁的开销.
核心模块: concurrent.futures模块
"""
from concurrent.futures import ThreadPoolExecutor, as_completed

"""
线程池实现原理:
1) 线程复用: 线程池创建预定义数量的线程,这些线程在程序的整个生命周期复用.
2) 任务队列: 线程池维护一个任务队列,当有任务交给线程池的时候,它们会被添加到这个队列中
3) 任务分配: 线程池中的空闲线程会从任务队列中取出任务并执行.如果所有的线程都在忙碌,那么新的任务会在
                    队列中等待,直到有线程空闲下来
"""
import time


# 使用线程池,还可以拿到返回值呢.
def task(n):
    print(f"任务编号 {n}")
    time.sleep(2)
    return f"任务编号 {n} 返回"


# 使用TreadPoolExecutor创建一个线程池
with ThreadPoolExecutor(max_workers=5) as executor:
    # 提交多个任务到线程池,返回一个Future对象,表示待执行的操作,可以类似当成是一个线程对象.
    futures = [executor.submit(task, i) for i in range(10)]
    # next(as_completed(futures)) # as_completed()返回一个迭代器,它的元素是提交给它的Future对象.
    # 在这些Future对象完成后,迭代器会依次返回它们.它可以以任务完成的顺序处理结果,而不是任务提交的顺序
    # 迭代器中返回.
    # 获取任务结果
    for future in as_completed(futures):
        try:
            result = future.result()
            print(result)
        except Exception as e:
            print(f"发生异常: {str(e)}")

print("所有的线程结束")


# region 2. future.result(timeout=None): 阻塞任务timeout秒,如果没有结果报错,如果有结果就返回结果
def task1(n):
    return n * n


with ThreadPoolExecutor(max_workers=5) as executor:
    future = executor.submit(task1, 10)
    result = future.result()  # 阻塞,直到任务完成并返回结果
    print(result)


# endregion

# region 3. executor.map(func,*iterables,timeout=None,chunksize=1)
# 类似于map函数,将iterables的参数带入到func进行计算,并返回一个迭代器,唯一不同的就是一个并发的执行func
def task2(n):
    time.sleep(2)
    return n * n


with ThreadPoolExecutor(max_workers=5) as executor:
    results = executor.map(task2, range(10))
    for result in results:
        print(result)

print("测试普通的map的耗时--------------------------")
start = time.time()
res = list(map(task2, range(10)))
print(f"普通map结束,耗时: {time.time() - start}")

# endregion

# region future.done() 检查Future对象是否已经完成. True表示已完成,False未完成

with ThreadPoolExecutor(max_workers=5) as executor:
    future = executor.submit(task2, 10)
    if future.done():  # 判断future是否完成
        result = future.result()
        print(result)

    future = executor.submit(task2, 20)
    canceled = future.cancel()  # 取消future任务,true表示取消成功
    print(canceled)
    print(future.cancelled())  # 查看future对象是否被取消
# endregion
